package com.workflow.workflowproject.serviceImpl;

import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.ObjectUtil;
import com.mybatisflex.core.util.StringUtil;
import com.workflow.workflowproject.entity.FlowForm;
import com.workflow.workflowproject.entity.FlowLogs;
import com.workflow.workflowproject.entity.dto.FlowNodeMessage;
import com.workflow.workflowproject.entity.dto.TaskInfoDto;
import com.workflow.workflowproject.entity.table.FlowFormTableDef;
import com.workflow.workflowproject.entity.table.FlowLogsTableDef;
import com.workflow.workflowproject.mapper.FlowFormMapper;
import com.workflow.workflowproject.mapper.FlowLogsMapper;
import com.workflow.workflowproject.mapper.FlowNodeApproveMapper;
import com.workflow.workflowproject.mapper.FlowNodeFieldMapper;
import com.workflow.workflowproject.pojo.lowflow.FlowNodeApprove;
import com.workflow.workflowproject.pojo.lowflow.FlowNodeField;
import com.workflow.workflowproject.pojo.lowflow.table.FlowNodeApproveTableDef;
import com.workflow.workflowproject.pojo.lowflow.table.FlowNodeFieldTableDef;
import com.workflow.workflowproject.service.ProcessToolsService;
import com.workflow.workflowproject.tools.Result.Result;
import com.workflow.workflowproject.until.FlowNodeUtil;
import org.apache.velocity.util.ArrayListWrapper;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.engine.HistoryService;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class ProcessToolsServiceImpl implements ProcessToolsService {
    @Autowired
    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    @Autowired
    private FlowFormMapper flowFormMapper;
    @Autowired
    private FlowNodeApproveMapper flowNodeApproveMapper;
    @Autowired
    private FlowLogsMapper flowLogsMapper;
    /**
     * 流程预期流程
     *
     * @param
     * @return
     */
    @Override
    public Result getExpectedNodes(TaskInfoDto taskInfoDto) throws Exception {
        String busKey = taskInfoDto.getBusKey();
        //如果没有业务ID
        QueryWrapper flowFormQueryWrapper = new QueryWrapper();
        flowFormQueryWrapper.where(FlowFormTableDef.FLOW_FORM.FLOW_INFO_ID.eq(taskInfoDto.getFlowInfoId()));
        FlowForm flowForm = flowFormMapper.selectOneByQuery(flowFormQueryWrapper);
        if(StringUtil.isBlank(busKey)){
            //如果不存在业务ID
            FlowNodeUtil flowNodeUtil = new FlowNodeUtil();
            List<FlowElement> flowNodeList = flowNodeUtil.calApprovePath(flowForm.getFlowBpmnXml(),taskInfoDto.getValue());
            List<FlowNodeMessage> flowNodeMessageList = new ArrayList<>();
            for(FlowElement flowElement : flowNodeList){
                FlowNodeMessage flowNodeMessage = new FlowNodeMessage();
                flowNodeMessage.setKey(flowElement.getId());
                flowNodeMessage.setName(flowElement.getName());
                flowNodeMessage.setFlowMessage("");
                flowNodeMessage.setApproverTime(null);
                flowNodeMessage.setIsPass(false);
                flowNodeMessage.setApprover("————");
                flowNodeMessage.setApproverId("");
                flowNodeMessage.setApprovalOpinion("");
                flowNodeMessage.setApprovalOpinionFilePath(new ArrayList<>());
                flowNodeMessageList.add(flowNodeMessage);
            }
            return Result.ok(flowNodeMessageList,flowNodeMessageList.size());
        }else{
            //如果有业务ID
            //查询是否有审批日志
            QueryWrapper flowLogsQueryWrapper = new QueryWrapper();
            flowLogsQueryWrapper.where(FlowLogsTableDef.FLOW_LOGS.BUS_KEY.eq(busKey));
            List<FlowLogs> flowLogsList = flowLogsMapper.selectListByQuery(flowLogsQueryWrapper);
            List<FlowNodeMessage> flowNodeMessageList = new ArrayList<>();
            if(CollectionUtil.isEmpty(flowLogsList)){
                FlowNodeUtil flowNodeUtil = new FlowNodeUtil();
                List<FlowElement> flowNodeList = flowNodeUtil.calApprovePath(flowForm.getFlowBpmnXml(),taskInfoDto.getValue());
                for(FlowElement flowElement : flowNodeList){
                    FlowNodeMessage flowNodeMessage = new FlowNodeMessage();
                    flowNodeMessage.setKey(flowElement.getId());
                    flowNodeMessage.setName(flowElement.getName());
                    flowNodeMessage.setFlowMessage("");
                    flowNodeMessage.setApproverTime(null);
                    flowNodeMessage.setIsPass(false);
                    flowNodeMessage.setApprover("————");
                    flowNodeMessage.setApproverId("");
                    flowNodeMessage.setApprovalOpinion("");
                    flowNodeMessage.setApprovalOpinionFilePath(new ArrayList<>());
                    flowNodeMessageList.add(flowNodeMessage);
                }
            }else{
                HashMap<String,FlowLogs> flowLogsHashMap = new HashMap<>();
                flowLogsList.forEach(item->{
                    flowLogsHashMap.put(item.getId(),item);
                });
                HistoryService historyService = processEngine.getHistoryService();
                HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
                        .processInstanceBusinessKey(busKey)
                        .orderByProcessInstanceStartTime().asc()
                        .singleResult();
                List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(historicProcessInstance.getId())
                        .orderByHistoricActivityInstanceStartTime().asc()
                        .list();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                for(HistoricActivityInstance historicActivityInstance : list){
                    if(StringUtil.isNotBlank(historicActivityInstance.getTaskId())){
                        FlowNodeMessage flowNodeMessage = new FlowNodeMessage();
                        flowNodeMessage.setKey(historicActivityInstance.getTaskId());
                        flowNodeMessage.setTaskNodeId(historicActivityInstance.getActivityId());
                        flowNodeMessage.setName(historicActivityInstance.getActivityName());
                        if(historicActivityInstance.getEndTime() != null){
                            flowNodeMessage.setApproverTime(simpleDateFormat.format(historicActivityInstance.getEndTime()));
                            flowNodeMessage.setIsPass(true);
                            if(!ObjectUtils.isEmpty(flowLogsHashMap.get(historicActivityInstance.getTaskId()))){
                                System.out.println("result:" + flowLogsHashMap.get(historicActivityInstance.getTaskId()).getResult());
                                flowNodeMessage.setFlowMessage(flowLogsHashMap.get(historicActivityInstance.getTaskId()).getResult());
                            }
                        }else{
                            flowNodeMessage.setApproverTime(null);
                            flowNodeMessage.setIsPass(false);
                            flowNodeMessage.setFlowMessage("待审核");
                        }
                        flowNodeMessage.setApprover(historicActivityInstance.getAssignee());
                        flowNodeMessage.setApproverId(historicActivityInstance.getAssignee());
                        flowNodeMessage.setApprovalOpinion("");
                        flowNodeMessage.setApprovalOpinionFilePath(new ArrayList<>());
                        flowNodeMessageList.add(flowNodeMessage);
                    }
                }
            }
            return Result.ok(flowNodeMessageList,flowNodeMessageList.size());
        }
    }
}
